/**
 * The utility to store and call a collection of listeners.
 *
 * @author Andrey Anisimov <hercules@inbox.ru>
 */

class Listeners {

    /**
     * @public
     * @param methods {Array} Array of {String}
     * @constructor
     */
    this.Listeners = function(methods) {
        this.map = {};
        for (var i = 0, n = methods.length; i < n; ++i) {
            var m = methods[i];
            this.map[m] = [];
        }
    };

    /**
     * @param l {Object}.
     */
    this.add = function(l) {
        var map = this.map;
        for (var key in map) {
            if (map.hasOwnProperty(key) && (typeof l[key] == 'function')) {
                var array = map[key];
                if (array.indexOf(l) < 0) {
                    array.push(l);
                }
            }
        }
    };

    /**
     * @param l {Object}
     */
    this.remove = function(l) {
        var map = this.map;
        for (var key in map) {
            if (map.hasOwnProperty(key)) {
                var array = map[key];
                var i = array.indexOf(l);
                if (i >= 0) {
                    array.splice(i, 1);
                }
            }
        }
    };

    /**
     * Calls the listener's method with the specified name. If the listener
     * does not have this method, omits it.
     *
     * @param method {String} The name of the method to call.
     * @param args {Array} [optional] The array of arguments.
     */
    this.call = function(method, args) {
        var array = this.map[method];
        if (!array) {
            return;
        }
        for (var i = 0, n = array.length; i < n; ++i) {
            var l = array[i];
            l && l[method].apply(l, args);
        }
    };
}